/* * ProActive Parallel Suite(TM): * The Open Source library for parallel and distributed * Workflows & Scheduling, Orchestration, Cloud Automation * and Big Data Analysis on Enterprise Grids & Clouds. * * Copyright (c) 2007 - 2017 ActiveEon * Contact: contact@activeeon.com * * This library is free software: you can redistribute it and/or * modify it under the terms of the GNU Affero General Public License * as published by the Free Software Foundation: version 3 of * the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * If needed, contact us to obtain a release under GPL Version 2 or 3 * or a different license than the AGPL. */ package org.ow2.proactive_grid_cloud_portal.studio; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStream; import java.security.KeyException; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; import javax.security.auth.login.LoginException; import javax.ws.rs.FormParam; import javax.ws.rs.HeaderParam; import javax.ws.rs.PathParam; import javax.ws.rs.core.PathSegment; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.log4j.Logger; import org.jboss.resteasy.annotations.providers.multipart.MultipartForm; import org.jboss.resteasy.plugins.providers.multipart.InputPart; import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput; import org.ow2.proactive_grid_cloud_portal.common.SchedulerRestInterface; import org.ow2.proactive_grid_cloud_portal.common.Session; import org.ow2.proactive_grid_cloud_portal.common.SharedSessionStore; import org.ow2.proactive_grid_cloud_portal.common.dto.LoginForm; import org.ow2.proactive_grid_cloud_portal.scheduler.SchedulerStateRest; import org.ow2.proactive_grid_cloud_portal.scheduler.dto.JobIdData; import org.ow2.proactive_grid_cloud_portal.scheduler.dto.JobValidationData; import org.ow2.proactive_grid_cloud_portal.scheduler.exception.JobCreationRestException; import org.ow2.proactive_grid_cloud_portal.scheduler.exception.NotConnectedRestException; import org.ow2.proactive_grid_cloud_portal.scheduler.exception.PermissionRestException; import org.ow2.proactive_grid_cloud_portal.scheduler.exception.SchedulerRestException; import org.ow2.proactive_grid_cloud_portal.scheduler.exception.SubmissionClosedRestException; import org.ow2.proactive_grid_cloud_portal.studio.storage.FileStorage; import org.ow2.proactive_grid_cloud_portal.studio.storage.FileStorageSupport; import org.ow2.proactive_grid_cloud_portal.studio.storage.FileStorageSupportFactory; import org.ow2.proactive_grid_cloud_portal.webapp.PortalConfiguration; public class StudioRest implements StudioInterface { private final static Logger logger = Logger.getLogger(StudioRest.class); private SchedulerStateRest schedulerRest = null; private SchedulerRestInterface scheduler() { if (schedulerRest == null) { schedulerRest = new SchedulerStateRest(); } return schedulerRest; } public static FileStorageSupport getFileStorageSupport() { return FileStorageSupportFactory.getInstance(); } private String getUserName(String sessionId) throws NotConnectedRestException { Session ss = SharedSessionStore.getInstance().get(sessionId); if (ss == null) { throw new NotConnectedRestException("you are not connected to the scheduler, you should log on first"); } return ss.getUserName(); } @Override public String login(@FormParam("username") String username, @FormParam("password") String password) throws KeyException, LoginException, SchedulerRestException { logger.info("Logging as " + username); return scheduler().login(username, password); } @Override public String loginWithCredential(@MultipartForm LoginForm multipart) throws IOException, KeyException, LoginException, SchedulerRestException { logger.info("Logging using credential file"); return scheduler().loginWithCredential(multipart); } @Override public void logout(@HeaderParam("sessionid") final String sessionId) throws PermissionRestException, NotConnectedRestException { logger.info("logout"); scheduler().disconnect(sessionId); } @Override public boolean isConnected(@HeaderParam("sessionid") String sessionId) { try { getUserName(sessionId); return true; } catch (NotConnectedRestException e) { return false; } } @Override public String currentUser(@HeaderParam("sessionid") String sessionId) { try { return getUserName(sessionId); } catch (NotConnectedRestException e) { return null; } } @Override public List<Workflow> getWorkflows(@HeaderParam("sessionid") String sessionId) throws NotConnectedRestException, IOException { String userName = getUserName(sessionId); logger.info("Reading workflows as " + userName); return getFileStorageSupport().getWorkflowStorage(userName).readAll(); } @Override public Workflow createWorkflow(@HeaderParam("sessionid") String sessionId, Workflow workflow) throws NotConnectedRestException, IOException { String userName = getUserName(sessionId); logger.info("Creating workflow as " + userName); return getFileStorageSupport().getWorkflowStorage(userName).store(workflow); } @Override public Workflow getWorkflow(@HeaderParam("sessionid") String sessionId, @PathParam("id") String workflowId) throws NotConnectedRestException, IOException { String userName = getUserName(sessionId); return getFileStorageSupport().getWorkflowStorage(userName).read(workflowId); } @Override public String getWorkflowXmlContent(@HeaderParam("sessionid") String sessionId, @PathParam("id") String workflowId) throws NotConnectedRestException, IOException { String userName = getUserName(sessionId); return getFileStorageSupport().getWorkflowStorage(userName).read(workflowId).getXml(); } @Override public Workflow updateWorkflow(@HeaderParam("sessionid") String sessionId, @PathParam("id") String workflowId, Workflow workflow) throws NotConnectedRestException, IOException { String userName = getUserName(sessionId); logger.info("Updating workflow " + workflowId + " as " + userName); return getFileStorageSupport().getWorkflowStorage(userName).update(workflowId, workflow); } @Override public void deleteWorkflow(@HeaderParam("sessionid") String sessionId, @PathParam("id") String workflowId) throws NotConnectedRestException, IOException { String userName = getUserName(sessionId); logger.info("Deleting workflow " + workflowId + " as " + userName); getFileStorageSupport().getWorkflowStorage(userName).delete(workflowId); } @Override public List<Workflow> getTemplates(@HeaderParam("sessionid") String sessionId) throws NotConnectedRestException, IOException { return getFileStorageSupport().getTemplateStorage().readAll(); } @Override public Workflow createTemplate(@HeaderParam("sessionid") String sessionId, Workflow template) throws NotConnectedRestException, IOException { return getFileStorageSupport().getTemplateStorage().store(template); } @Override public Workflow getTemplate(@HeaderParam("sessionid") String sessionId, @PathParam("id") String templateId) throws NotConnectedRestException, IOException { return getFileStorageSupport().getTemplateStorage().read(templateId); } @Override public String getTemplateXmlContent(@HeaderParam("sessionid") String sessionId, @PathParam("id") String templateId) throws NotConnectedRestException, IOException { return getFileStorageSupport().getTemplateStorage().read(templateId).getXml(); } @Override public Workflow updateTemplate(@HeaderParam("sessionid") String sessionId, @PathParam("id") String templateId, Workflow template) throws NotConnectedRestException, IOException { return getFileStorageSupport().getTemplateStorage().update(templateId, template); } @Override public void deleteTemplate(@HeaderParam("sessionid") String sessionId, @PathParam("id") String templateId) throws NotConnectedRestException, IOException { getFileStorageSupport().getTemplateStorage().delete(templateId); } @Override public List<Script> getScripts(@HeaderParam("sessionid") String sessionId) throws NotConnectedRestException, IOException { String userName = getUserName(sessionId); return getFileStorageSupport().getScriptStorage(userName).readAll(); } @Override public String createScript(@HeaderParam("sessionid") String sessionId, @FormParam("name") String name, @FormParam("content") String content) throws NotConnectedRestException, IOException { String userName = getUserName(sessionId); FileStorage<Script> scriptStorage = getFileStorageSupport().getScriptStorage(userName); Script storedScript = scriptStorage.store(new Script(name, content)); return storedScript.getAbsolutePath(); } @Override public String updateScript(@HeaderParam("sessionid") String sessionId, @PathParam("name") String name, @FormParam("content") String content) throws NotConnectedRestException, IOException { return createScript(sessionId, name, content); } @Override public ArrayList<String> getClasses(@HeaderParam("sessionid") String sessionId) throws NotConnectedRestException { String userName = getUserName(sessionId); File classesDir = new File(getFileStorageSupport().getWorkflowsDir(userName), "classes"); ArrayList<String> classes = new ArrayList<>(); if (classesDir.exists()) { File[] jars = classesDir.listFiles(new FilenameFilter() { public boolean accept(File dir, String name) { return name.toLowerCase().endsWith(".jar"); } }); for (File jar : jars) { try { JarFile jarFile = new JarFile(jar.getAbsolutePath()); Enumeration allEntries = jarFile.entries(); while (allEntries.hasMoreElements()) { JarEntry entry = (JarEntry) allEntries.nextElement(); String name = entry.getName(); if (name.endsWith(".class")) { String noExt = name.substring(0, name.length() - ".class".length()); classes.add(noExt.replaceAll("/", ".")); } } } catch (IOException e) { logger.warn("Could not read jar file " + jar, e); } } } return classes; } @Override public String createClass(@HeaderParam("sessionid") String sessionId, MultipartFormDataInput input) throws NotConnectedRestException, IOException { String userName = getUserName(sessionId); File classesDir = new File(getFileStorageSupport().getWorkflowsDir(userName), "classes"); if (!classesDir.exists()) { logger.info("Creating dir " + classesDir.getAbsolutePath()); classesDir.mkdirs(); } String fileName = ""; Map<String, List<InputPart>> uploadForm = input.getFormDataMap(); String name = uploadForm.keySet().iterator().next(); List<InputPart> inputParts = uploadForm.get(name); for (InputPart inputPart : inputParts) { try { //convert the uploaded file to inputstream InputStream inputStream = inputPart.getBody(InputStream.class, null); byte[] bytes = IOUtils.toByteArray(inputStream); //constructs upload file path fileName = classesDir.getAbsolutePath() + "/" + name; FileUtils.writeByteArrayToFile(new File(fileName), bytes); } catch (IOException e) { logger.warn("Could not read input part", e); throw e; } } return fileName; } @Override public JobValidationData validate(@PathParam("path") PathSegment pathSegment, MultipartFormDataInput multipart) { return scheduler().validate(pathSegment, multipart); } @Override public JobIdData submit(@HeaderParam("sessionid") String sessionId, @PathParam("path") PathSegment pathSegment, MultipartFormDataInput multipart) throws JobCreationRestException, NotConnectedRestException, PermissionRestException, SubmissionClosedRestException, IOException { return scheduler().submit(sessionId, pathSegment, multipart); } @Override public String submitPlannings(String sessionId, PathSegment pathSegment, Map<String, String> jobContentXmlString) throws JobCreationRestException, NotConnectedRestException, PermissionRestException, SubmissionClosedRestException, IOException { return scheduler().submitPlannings(sessionId, pathSegment, jobContentXmlString); } @Override public String getVisualization(@HeaderParam("sessionid") String sessionId, @PathParam("id") String jobId) throws NotConnectedRestException, IOException { File visualizationFile = new File(PortalConfiguration.jobIdToPath(jobId) + ".html"); if (visualizationFile.exists()) { return FileUtils.readFileToString(new File(visualizationFile.getAbsolutePath())); } return ""; } @Override public boolean updateVisualization(@HeaderParam("sessionid") String sessionId, @PathParam("id") String jobId, @FormParam("visualization") String visualization) throws NotConnectedRestException, IOException { File visualizationFile = new File(PortalConfiguration.jobIdToPath(jobId) + ".html"); if (visualizationFile.exists()) { visualizationFile.delete(); } FileUtils.write(new File(visualizationFile.getAbsolutePath()), visualization); return true; } }